/*
 * 实现server和client之间的消息分发，根据不同消息类型，调用不同的回调函数
 */
#pragma once
#include "net.hpp"
#include "message.hpp"

namespace jsonrpc
{
    class Callback
    {
    public:
        using ptr = std::shared_ptr<Callback>;
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;
    };

    template <class T>
    class CallbackTemplate : public Callback
    {
    public:
        using ptr = std::shared_ptr<CallbackTemplate<T>>;
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T> &msg)>;
        CallbackTemplate(const MessageCallback &handler) : _handler(handler) {}
        virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) override
        {
            auto t_msg = std::dynamic_pointer_cast<T>(msg);
            if (t_msg)
            {
                _handler(conn, t_msg);
            }
        }

    private:
        MessageCallback _handler;
    };

    class Dispatcher
    {
    public:
        using ptr = std::shared_ptr<Dispatcher>;
        template <class T>
        void registerHandler(MType mtype, const typename CallbackTemplate<T>::MessageCallback &handler)
        {
            std::unique_lock<std::mutex> lock(mtx);
            auto cb = std::make_shared<CallbackTemplate<T>>(handler);
            _handlers[mtype] = cb;
        }

        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg)
        {
            std::unique_lock<std::mutex> lock(mtx);
            auto it = _handlers.find(msg->getMessageType());
            if (it != _handlers.end())
            {
                it->second->onMessage(conn, msg);
            }
            // 没有找到对应的回调函数，关闭连接
            LOG_ERROR("no handler for message type: %d", msg->getMessageType());
            conn->shutdown();
        }

    private:
        std::mutex mtx;
        std::unordered_map<MType, Callback::ptr> _handlers;
    };
}